home *** CD-ROM | disk | FTP | other *** search
/ Suzy B Software 2 / Suzy B Software CD-ROM 2 (1994).iso / new_file / mintprgs / mint112s / mint112s.lzh / fasttext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-30  |  26.9 KB  |  1,412 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1992,1993,1994 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. #include "mint.h"
  8. #include "fasttext.h"
  9.  
  10. #ifdef FASTTEXT
  11.  
  12. #ifdef __GNUC__
  13. #define ITYPE long    /* gcc's optimizer likes 32 bit integers */
  14. #else
  15. #define ITYPE int
  16. #endif
  17.  
  18. #define CONDEV    (2)
  19.  
  20. static SCREEN *current;
  21. static short scr_usecnt;
  22.  
  23. static void paint P_((SCREEN *, int, char *)),
  24.      paint8c P_((SCREEN *, int, char *)),
  25.      paint816m P_((SCREEN *, int, char *));
  26.  
  27. INLINE static void curs_off P_((SCREEN *)), curs_on P_((SCREEN *));
  28. INLINE static void flash P_((SCREEN *));
  29. static void normal_putch P_((SCREEN *, int));
  30. static void escy_putch P_((SCREEN *, int));
  31. static void quote_putch P_((SCREEN *, int));
  32.  
  33. static    char *chartab[256];
  34.  
  35. #define MAX_PLANES 8
  36. static int fgmask[MAX_PLANES], bgmask[MAX_PLANES];
  37.  
  38. static long scrnsize;
  39.  
  40. short hardscroll;
  41. static char *hardbase, *oldbase;
  42.  
  43. typedef void (*Vfunc) P_((SCREEN *, int));
  44.  
  45. #define base *((char **)0x44eL)
  46. #define escy1 *((short *)0x4acL)
  47.  
  48. static Vfunc state;
  49.  
  50. static short hardline;
  51. static void (*vpaint) P_((SCREEN *, int, char *));
  52. static char *rowoff;
  53.  
  54. void init P_((void));
  55. void hardware_scroll P_((SCREEN *));
  56. INLINE static char *PLACE P_((SCREEN *, int, int));
  57. INLINE static void gotoxy P_((SCREEN *, int, int));
  58. INLINE static void clrline P_((SCREEN *, int));
  59. INLINE static void clear P_((SCREEN *));
  60. INLINE static void clrchar P_((SCREEN *, int, int));
  61. INLINE static void clrfrom P_((SCREEN *, int, int, int, int));
  62. INLINE static void delete_line P_((SCREEN *, int));
  63. INLINE static void insert_line P_((SCREEN *, int));
  64. static void setbgcol P_((SCREEN *, int));
  65. static void setfgcol P_((SCREEN *, int));
  66. static void setcurs P_((SCREEN *, int));
  67. static void putesc P_((SCREEN *, int));
  68. static void escy1_putch P_((SCREEN *, int));
  69. INLINE static void put_ch P_((SCREEN *, int));
  70.  
  71. /* routines for flashing the cursor for screen v */
  72. /* flash(v): invert the character currently under the cursor */
  73.  
  74. INLINE static void
  75. flash(v)
  76.     SCREEN *v;
  77. {
  78.     char *place;
  79.     ITYPE i, j, vplanes;
  80.  
  81.     vplanes = v->planes + v->planes;
  82.     place = v->cursaddr;
  83.  
  84.     for (j = v->cheight; j > 0; --j) {
  85.         for (i = 0; i < vplanes; i+=2)
  86.             place[i] = ~place[i];
  87.  
  88.         place += v->planesiz;
  89.     }
  90.     v->curstimer = v->period;
  91. }
  92.  
  93. /* make sure the cursor is off */
  94.  
  95. INLINE
  96. static void
  97. curs_off(v)
  98.     SCREEN *v;
  99. {
  100.     if (v->flags & CURS_ON) {
  101.         if (v->flags & CURS_FSTATE) {
  102.             flash(v);
  103.             v->flags &= ~CURS_FSTATE;
  104.         }
  105.     }
  106. }
  107.  
  108. /* OK, show the cursor again (if appropriate) */
  109.  
  110. INLINE static void
  111. curs_on(v)
  112.     SCREEN *v;
  113. {
  114.     if (v->hidecnt) return;
  115.  
  116.     if (v->flags & CURS_ON) {
  117. #if 0
  118.     /* if the cursor is flashing, we cheat a little and leave it off
  119.      * to be turned on again (if necessary) by the VBL routine
  120.      */
  121.         if (v->flags & CURS_FLASH) {
  122.             v->curstimer = 2;
  123.             return;
  124.         }
  125. #endif
  126.         if (!(v->flags & CURS_FSTATE)) {
  127.             v->flags |= CURS_FSTATE;
  128.             flash(v);
  129.         }
  130.     }
  131. }
  132.  
  133. void
  134. init()
  135. {
  136.     SCREEN *v;
  137.     int i, j;
  138.     char *data, *foo;
  139.     static char chardata[256*16];
  140.     register int linelen;
  141.  
  142.     foo = lineA0();
  143.     v = (SCREEN *)(foo - 346);
  144.     
  145.     /* Ehem... The screen might be bigger than 32767 bytes.
  146.        Let's do some casting... 
  147.        Erling
  148.     */
  149.     linelen = v->linelen;
  150.     scrnsize = (v->maxy+1)*(long)linelen;
  151.     rowoff = (char *)kmalloc((long)((v->maxy+1) * sizeof(long)));
  152.     if (rowoff == 0) {
  153.         FATAL("Insufficient memory for screen offset table!");
  154.     } else {
  155.         long off, *lptr = (long *)rowoff;
  156.         for (i=0, off=0; i<=v->maxy; i++) {
  157.             *lptr++ = off;
  158.             off += linelen;
  159.         }
  160.     }
  161.     if (hardscroll == -1) {
  162.     /* request for auto-setting */
  163.         hardscroll = v->maxy+1;
  164.     }
  165.     if (hardscroll > 0) {
  166.         if (!hardbase)
  167.             hardbase = (char *)(((long)kcore(SCNSIZE(v)+256L)+255L)
  168.                        & 0xffffff00L);
  169.  
  170.         if (hardbase == 0) {
  171.             ALERT("Insufficient memory for hardware scrolling!");
  172.         } else {
  173.             v->curstimer = 0x7f;
  174.             quickmove(hardbase, base, scrnsize);
  175.             v->cursaddr = v->cursaddr + (hardbase - base);
  176.             oldbase = base;
  177.             base = hardbase;
  178.             Setscreen(hardbase, hardbase, -1);
  179.             v->curstimer = v->period;
  180.         }
  181.     }
  182.     hardline = 0;
  183.     if (v->cheight == 8 && v->planes == 2) {
  184.         foo = &chardata[0];
  185.         vpaint = paint8c;
  186.         for (i = 0; i < 256; i++) {
  187.             chartab[i] = foo;
  188.             data = v->fontdata + i;
  189.             for (j = 0; j < 8; j++) {
  190.                 *foo++ = *data;
  191.                 data += v->form_width;
  192.             }
  193.         }
  194.     } else if ((v->cheight == 16 || v->cheight == 8) && v->planes == 1) {
  195.         foo = &chardata[0];
  196.         vpaint = paint816m;
  197.         for (i = 0; i < 256; i++) {
  198.             chartab[i] = foo;
  199.             data = v->fontdata + i;
  200.             for (j = 0; j < v->cheight; j++) {
  201.                 *foo++ = *data;
  202.                 data += v->form_width;
  203.             }
  204.         }
  205.     }
  206.     else
  207.         vpaint = paint;
  208.  
  209.     if (v->hidecnt == 0) {
  210.     /*
  211.      * make sure the cursor is set up correctly and turned on
  212.      */
  213.         (void)Cursconf(0,0);    /* turn cursor off */
  214.  
  215.         v->flags &= ~CURS_FSTATE;
  216.  
  217.     /* now turn the cursor on the way we like it */
  218.         v->curstimer = v->period;
  219.         v->hidecnt = 0;
  220.         v->flags |= CURS_ON;
  221.         curs_on(v);
  222.     } else {
  223.         (void)Cursconf(0,0);
  224.         v->flags &= ~CURS_ON;
  225.         v->hidecnt = 1;
  226.     }
  227.  
  228.     current = v;
  229.     /* setup bgmask and fgmask */
  230.     setbgcol(v, v->bgcol);
  231.     setfgcol(v, v->fgcol);
  232.     state = normal_putch;
  233. }
  234.  
  235. /*
  236.  * PLACE(v, x, y): the address corresponding to the upper left hand corner of
  237.  * the character at position (x,y) on screen v
  238.  */
  239. INLINE static
  240. char *PLACE(v, x, y)
  241.     SCREEN *v;
  242.     int x, y;
  243. {
  244.     char *place;
  245.     int i, j;
  246.  
  247.     place = base + x;
  248.     if (y == v->maxy)
  249.         place += scrnsize - v->linelen;
  250.     else if (y) {
  251.         y+=y;    /* Make Y into index for longword array. */
  252.         y+=y;    /* Two word-size adds are faster than a 2-bit shift. */
  253.         place += *(long *)(rowoff + y);
  254.     }
  255.     if ((j = v->planes-1)) {
  256.         i = (x & 0xfffe);
  257.         do place += i;
  258.         while (--j);
  259.     }
  260.     return place;
  261. }
  262.  
  263. /*
  264.  * paint(v, c, place): put character 'c' at position 'place' on screen
  265.  * v. It is assumed that x, y are proper coordinates!
  266.  * Specialized versions (paint8c and paint816m) of this routine follow;
  267.  * they assume 8 line high characters, medium res. and 8 or 16 line/mono,
  268.  * respectively.
  269.  */
  270.  
  271. static void
  272. paint(v, c, place)
  273.     SCREEN *v;
  274.     int c;
  275.     char *place;
  276. {
  277.     char *data, d, doinverse;
  278.     ITYPE j, planecount;
  279.     int vplanes;
  280.     long vform_width, vplanesiz;
  281.  
  282.     vplanes = v->planes;
  283.  
  284.     data = v->fontdata + c;
  285.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  286.     vform_width = v->form_width;
  287.     vplanesiz = v->planesiz;
  288.  
  289.     for (j = v->cheight; j > 0; --j) {
  290.         d = *data ^ doinverse;
  291.         for (planecount = 0; planecount < vplanes; planecount++)
  292.           place[planecount << 1]
  293.             = ((d & (char) fgmask[planecount])
  294.                | (~d & (char) bgmask[planecount]));
  295.         place += vplanesiz;
  296.         data += vform_width;
  297.     }
  298. }
  299.  
  300. static void
  301. paint8c(v, c, place)
  302.     SCREEN *v;
  303.     int c;
  304.     char *place;
  305. {
  306.     char *data;
  307.     char d, doinverse;
  308.     char bg0, bg1, fg0, fg1;
  309.     long vplanesiz;
  310.  
  311.     data = chartab[c];
  312.  
  313.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  314.     vplanesiz = v->planesiz;
  315.     bg0 = bgmask[0];
  316.     bg1 = bgmask[1];
  317.     fg0 = fgmask[0];
  318.     fg1 = fgmask[1];
  319.  
  320.     if (!doinverse && !bg0 && !bg1 && fg0 && fg1) {
  321.         /* line 1 */
  322.         d = *data++;
  323.         *place = d;
  324.         place[2] = d;
  325.         place += vplanesiz;
  326.  
  327.         /* line 2 */
  328.         d = *data++;
  329.         *place = d;
  330.         place[2] = d;
  331.         place += vplanesiz;
  332.  
  333.         /* line 3 */
  334.         d = *data++;
  335.         *place = d;
  336.         place[2] = d;
  337.         place += vplanesiz;
  338.  
  339.         /* line 4 */
  340.         d = *data++;
  341.         *place = d;
  342.         place[2] = d;
  343.         place += vplanesiz;
  344.  
  345.         /* line 5 */
  346.         d = *data++;
  347.         *place = d;
  348.         place[2] = d;
  349.         place += vplanesiz;
  350.  
  351.         /* line 6 */
  352.         d = *data++;
  353.         *place = d;
  354.         place[2] = d;
  355.         place += vplanesiz;
  356.  
  357.         /* line 7 */
  358.         d = *data++;
  359.         *place = d;
  360.         place[2] = d;
  361.         place += vplanesiz;
  362.  
  363.         /* line 8 */
  364.         d = *data;
  365.         *place = d;
  366.         place[2] = d;
  367.     } else {
  368.         /* line 1 */
  369.         d = *data++ ^ doinverse;
  370.         *place = ((d & fg0) | (~d & bg0));
  371.         place[2] = ((d & fg1) | (~d & bg1));
  372.         place += vplanesiz;
  373.  
  374.         /* line 2 */
  375.         d = *data++ ^ doinverse;
  376.         *place = ((d & fg0) | (~d & bg0));
  377.         place[2] = ((d & fg1) | (~d & bg1));
  378.         place += vplanesiz;
  379.  
  380.         /* line 3 */
  381.         d = *data++ ^ doinverse;
  382.         *place = ((d & fg0) | (~d & bg0));
  383.         place[2] = ((d & fg1) | (~d & bg1));
  384.         place += vplanesiz;
  385.  
  386.         /* line 4 */
  387.         d = *data++ ^ doinverse;
  388.         *place = ((d & fg0) | (~d & bg0));
  389.         place[2] = ((d & fg1) | (~d & bg1));
  390.         place += vplanesiz;
  391.  
  392.         /* line 5 */
  393.         d = *data++ ^ doinverse;
  394.         *place = ((d & fg0) | (~d & bg0));
  395.         place[2] = ((d & fg1) | (~d & bg1));
  396.         place += vplanesiz;
  397.  
  398.         /* line 6 */
  399.         d = *data++ ^ doinverse;
  400.         *place = ((d & fg0) | (~d & bg0));
  401.         place[2] = ((d & fg1) | (~d & bg1));
  402.         place += vplanesiz;
  403.  
  404.         /* line 7 */
  405.         d = *data++ ^ doinverse;
  406.         *place = ((d & fg0) | (~d & bg0));
  407.         place[2] = ((d & fg1) | (~d & bg1));
  408.         place += vplanesiz;
  409.  
  410.         /* line 8 */
  411.         d = *data ^ doinverse;
  412.         *place = ((d & fg0) | (~d & bg0));
  413.         place[2] = ((d & fg1) | (~d & bg1));
  414.     }
  415. }
  416.  
  417. static void
  418. paint816m(v, c, place)
  419.     SCREEN *v;
  420.     int c;
  421.     char *place;
  422. {
  423.     char *data;
  424.     char d, doinverse;
  425.     long vplanesiz;
  426.  
  427.     data = chartab[c];
  428.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  429.     doinverse ^= bgmask[0];
  430.     vplanesiz = v->planesiz;
  431.  
  432.     if (bgmask[0] == fgmask[0])
  433.       {
  434.         /* fgcol and bgcol are the same -- easy */
  435.         d = (char) bgmask[0];
  436.         *place = d;
  437.         place += vplanesiz;
  438.         *place = d;
  439.         place += vplanesiz;
  440.         *place = d;
  441.         place += vplanesiz;
  442.         *place = d;
  443.         place += vplanesiz;
  444.         *place = d;
  445.         place += vplanesiz;
  446.         *place = d;
  447.         place += vplanesiz;
  448.         *place = d;
  449.         place += vplanesiz;
  450.         *place = d;
  451.         if (v->cheight == 8)
  452.         return;
  453.         place += vplanesiz;
  454.         *place = d;
  455.         place += vplanesiz;
  456.         *place = d;
  457.         place += vplanesiz;
  458.         *place = d;
  459.         place += vplanesiz;
  460.         *place = d;
  461.         place += vplanesiz;
  462.         *place = d;
  463.         place += vplanesiz;
  464.         *place = d;
  465.         place += vplanesiz;
  466.         *place = d;
  467.         place += vplanesiz;
  468.         *place = d;
  469.       }
  470.     else if (!doinverse) {
  471.         /* line 1 */
  472.         d = *data++;
  473.         *place = d;
  474.         place += vplanesiz;
  475.  
  476.         /* line 2 */
  477.         d = *data++;
  478.         *place = d;
  479.         place += vplanesiz;
  480.  
  481.         /* line 3 */
  482.         d = *data++;
  483.         *place = d;
  484.         place += vplanesiz;
  485.  
  486.         /* line 4 */
  487.         d = *data++;
  488.         *place = d;
  489.         place += vplanesiz;
  490.  
  491.         /* line 5 */
  492.         d = *data++;
  493.         *place = d;
  494.         place += vplanesiz;
  495.  
  496.         /* line 6 */
  497.         d = *data++;
  498.         *place = d;
  499.         place += vplanesiz;
  500.  
  501.         /* line 7 */
  502.         d = *data++;
  503.         *place = d;
  504.         place += vplanesiz;
  505.  
  506.         /* line 8 */
  507.         d = *data++;
  508.         *place = d;
  509.  
  510.         if (v->cheight == 8)
  511.             return;
  512.  
  513.         place += vplanesiz;
  514.  
  515.         /* line 9 */
  516.         d = *data++;
  517.         *place = d;
  518.         place += vplanesiz;
  519.  
  520.         /* line 10 */
  521.         d = *data++;
  522.         *place = d;
  523.         place += vplanesiz;
  524.  
  525.         /* line 11 */
  526.         d = *data++;
  527.         *place = d;
  528.         place += vplanesiz;
  529.  
  530.         /* line 12 */
  531.         d = *data++;
  532.         *place = d;
  533.         place += vplanesiz;
  534.  
  535.         /* line 13 */
  536.         d = *data++;
  537.         *place = d;
  538.         place += vplanesiz;
  539.  
  540.         /* line 14 */
  541.         d = *data++;
  542.         *place = d;
  543.         place += vplanesiz;
  544.  
  545.         /* line 15 */
  546.         d = *data++;
  547.         *place = d;
  548.         place += vplanesiz;
  549.  
  550.         /* line 16 */
  551.         d = *data;
  552.         *place = d;
  553.     } else {
  554.         /* line 1 */
  555.         d = ~*data++;
  556.         *place = d;
  557.         place += vplanesiz;
  558.  
  559.         /* line 2 */
  560.         d = ~*data++;
  561.         *place = d;
  562.         place += vplanesiz;
  563.  
  564.         /* line 3 */
  565.         d = ~*data++;
  566.         *place = d;
  567.         place += vplanesiz;
  568.  
  569.         /* line 4 */
  570.         d = ~*data++;
  571.         *place = d;
  572.         place += vplanesiz;
  573.  
  574.         /* line 5 */
  575.         d = ~*data++;
  576.         *place = d;
  577.         place += vplanesiz;
  578.  
  579.         /* line 6 */
  580.         d = ~*data++;
  581.         *place = d;
  582.         place += vplanesiz;
  583.  
  584.         /* line 7 */
  585.         d = ~*data++;
  586.         *place = d;
  587.         place += vplanesiz;
  588.  
  589.         /* line 8 */
  590.         d = ~*data++;
  591.         *place = d;
  592.  
  593.         if (v->cheight == 8)
  594.             return;
  595.  
  596.         place += vplanesiz;
  597.  
  598.         /* line 9 */
  599.         d = ~*data++;
  600.         *place = d;
  601.         place += vplanesiz;
  602.  
  603.         /* line 10 */
  604.         d = ~*data++;
  605.         *place = d;
  606.         place += vplanesiz;
  607.  
  608.         /* line 11 */
  609.         d = ~*data++;
  610.         *place = d;
  611.         place += vplanesiz;
  612.  
  613.         /* line 12 */
  614.         d = ~*data++;
  615.         *place = d;
  616.         place += vplanesiz;
  617.  
  618.         /* line 13 */
  619.         d = ~*data++;
  620.         *place = d;
  621.         place += vplanesiz;
  622.  
  623.         /* line 14 */
  624.         d = ~*data++;
  625.         *place = d;
  626.         place += vplanesiz;
  627.  
  628.         /* line 15 */
  629.         d = ~*data++;
  630.         *place = d;
  631.         place += vplanesiz;
  632.  
  633.         /* line 16 */
  634.         d = ~*data;
  635.         *place = d;
  636.     }
  637. }
  638.  
  639. /*
  640.  * gotoxy (v, x, y): move current cursor address of screen v to (x, y)
  641.  * makes sure that (x, y) will be legal
  642.  */
  643.  
  644. INLINE static void
  645. gotoxy(v, x, y)
  646.     SCREEN *v;
  647.     int x, y;
  648. {
  649.     if (x > v->maxx) x = v->maxx;
  650.     else if (x < 0) x = 0;
  651.     if (y > v->maxy) y = v->maxy;
  652.     else if (y < 0) y = 0;
  653.  
  654.     v->cx = x;
  655.     v->cy = y;
  656.     v->cursaddr = PLACE(v, x, y);
  657. }
  658.  
  659. /*
  660.  * clrline(v, r): clear line r of screen v
  661.  */
  662.  
  663. INLINE static void
  664. clrline(v, r)
  665.     SCREEN *v;
  666.     int r;
  667. {
  668.     int *dst, *m;
  669.     long nwords;
  670.     int i, vplanes;
  671.  
  672.     /* Hey, again the screen might be bigger than 32767 bytes.
  673.        Do another cast... */
  674.     r += r;
  675.     r += r;
  676.     dst = (int *)(base + *(long *)(rowoff+r));
  677.     if (v->bgcol == 0)
  678.       zero((char *)dst, v->linelen);
  679.     else
  680.       {
  681.         /* do it the hard way */
  682.         vplanes = v->planes;
  683.         for (nwords = v->linelen >> 1; nwords > 0; nwords -= vplanes)
  684.           {
  685.         m = bgmask;
  686.         for (i = 0; i < vplanes; i++)
  687.           *dst++ = *m++;
  688.           }
  689.       }
  690. }
  691.     
  692. /*
  693.  * clear(v): clear the whole screen v
  694.  */
  695.  
  696. INLINE static void
  697. clear(v)
  698.     SCREEN *v;
  699. {
  700.     int i, vplanes;
  701.     int *dst, *m;
  702.     long nwords;
  703.  
  704.     if (v->bgcol == 0)
  705.       zero(base, scrnsize);
  706.     else
  707.       {
  708.         /* do it the hard way */
  709.         dst = (int *) base;
  710.         vplanes = v->planes;
  711.         for (nwords = scrnsize >> 1; nwords > 0; nwords -= vplanes)
  712.           {
  713.         m = bgmask;
  714.         for (i = 0; i < vplanes; i++)
  715.           *dst++ = *m++;
  716.           }
  717.       }
  718. }
  719.  
  720. /*
  721.  * clrchar(v, x, y): clear the (x,y) position on screen v
  722.  */
  723.  
  724. INLINE static void
  725. clrchar(v, x, y)
  726.     SCREEN *v;
  727.     int x, y;
  728. {
  729.     int i, j, vplanes;
  730.     char *place;
  731.     int *m;
  732.  
  733.     vplanes = v->planes + v->planes;
  734.  
  735.     place = PLACE(v, x, y);
  736.  
  737.     for (j = v->cheight; j > 0; --j) {
  738.         m = bgmask;
  739.         for (i = 0; i < vplanes; i += 2)
  740.             place[i] = (char) *m++;
  741.         place += v->planesiz;
  742.     }
  743. }
  744.  
  745. /*
  746.  * clrfrom(v, x1, y1, x2, y2): clear screen v from position (x1,y1) to
  747.  * position (x2, y2) inclusive. It is assumed that y2 >= y1.
  748.  */
  749.  
  750. INLINE static void
  751. clrfrom(v, x1, y1, x2, y2)
  752.     SCREEN *v;
  753.     int x1,y1,x2,y2;
  754. {
  755.     int i;
  756.  
  757.     for (i = x1; i <= v->maxx; i++)
  758.         clrchar(v, i, y1);
  759.     if (y2 > y1) {
  760.         for (i = 0; i <= x2; i++)
  761.             clrchar(v, i, y2);
  762.         for (i = y1+1; i < y2; i++)
  763.             clrline(v, i);
  764.     }
  765. }
  766.  
  767. /*
  768.  * scroll a screen in hardware; if we still have hardware scrolling lines left,
  769.  * just move the physical screen base, otherwise copy the screen back to the
  770.  * hardware base and start over
  771.  */
  772. void
  773. hardware_scroll(v)
  774.     SCREEN *v;
  775. {
  776.  
  777.     ++hardline;
  778.     if (hardline < hardscroll) { /* just move the screen */
  779.         base += v->linelen;
  780.     } else {
  781.         hardline = 0;
  782.         quickmove(hardbase, base + v->linelen, scrnsize - v->linelen);
  783.         base = hardbase;
  784.     }
  785.     v->cursaddr = PLACE(v, v->cx, v->cy);
  786.     Setscreen(base, base, -1);
  787. }
  788.  
  789. /*
  790.  * delete_line(v, r): delete line r of screen v. The screen below this
  791.  * line is scrolled up, and the bottom line is cleared.
  792.  */
  793.  
  794. #define scroll(v) delete_line(v, 0)
  795.  
  796. INLINE static void
  797. delete_line(v, r)
  798.     SCREEN *v;
  799.     int r;
  800. {
  801.     long *src, *dst, nbytes;
  802.  
  803.     if (r == 0) {
  804.         if (hardbase) {
  805.             hardware_scroll(v);
  806.             clrline(v, v->maxy);
  807.             return;
  808.         }
  809.         nbytes = scrnsize - v->linelen;
  810.     } else {
  811.         register int i = v->maxy - r;
  812.         i += i;
  813.         i += i;
  814.         nbytes = *(long *)(rowoff+i);
  815.     }
  816.  
  817.     /* Sheeze, how many times do we really have to cast... 
  818.        Erling.    
  819.     */
  820.  
  821.     r += r;
  822.     r += r;
  823.     dst = (long *)(base + *(long *)(rowoff + r));
  824.     src = (long *)( ((long)dst) + v->linelen);
  825.  
  826.     quickmove(dst, src, nbytes);
  827.  
  828. /* clear the last line */
  829.     clrline(v, v->maxy);
  830. }
  831.  
  832. /*
  833.  * insert_line(v, r): scroll all of the screen starting at line r down,
  834.  * and then clear line r.
  835.  */
  836.  
  837. INLINE static void
  838. insert_line(v, r)
  839.     SCREEN *v;
  840.     int r;
  841. {
  842.     long *src, *dst;
  843.     int i, j, linelen;
  844.  
  845.     i = v->maxy - 1;
  846.     i += i;
  847.     i += i;
  848.     j = r+r;
  849.     j += j;
  850.     linelen = v->linelen;
  851.     src = (long *)(base + *(long *)(rowoff + i));
  852.     dst = (long *)((long)src + linelen);
  853.     for (; i >= j ; i -= 4) {
  854.     /* move line i to line i+1 */
  855.         quickmove(dst, src, linelen);
  856.         dst = src;
  857.         src = (long *)((long) src - linelen);
  858.     }
  859.  
  860. /* clear line r */
  861.     clrline(v, r);
  862. }
  863.  
  864. /*
  865.  * special states for handling ESC b x and ESC c x. Note that for now,
  866.  * color is ignored.
  867.  */
  868.  
  869. static void
  870. setbgcol(v, c)
  871.     SCREEN *v;
  872.     int c;
  873. {
  874.     int i;
  875.  
  876.     v->bgcol = c & ((1 << v->planes)-1);
  877.     for (i = 0; i < v->planes; i++)
  878.         bgmask[i] = (v->bgcol & (1 << i)) ? -1 : 0;
  879.     state = normal_putch;
  880. }
  881.  
  882. static void
  883. setfgcol(v, c)
  884.     SCREEN *v;
  885.     int c;
  886. {
  887.     int i;
  888.  
  889.     v->fgcol = c & ((1 << v->planes)-1);
  890.     for (i = 0; i < v->planes; i++)
  891.         fgmask[i] = (v->fgcol & (1 << i)) ? -1 : 0;
  892.     state = normal_putch;
  893. }
  894.  
  895. static void
  896. setcurs(v, c)
  897.     SCREEN *v;
  898.     int c;
  899. {
  900.     c -= ' ';
  901.     if (!c) {
  902.         v->flags &= ~CURS_FLASH;
  903.     } else {
  904.         v->flags |= CURS_FLASH;
  905.         v->period = (unsigned char) c;
  906.     }
  907.     state = normal_putch;
  908. }
  909.  
  910. static void
  911. quote_putch(v, c)
  912.     SCREEN *v;
  913.     int c;
  914. {
  915.     (*vpaint)(v, c, v->cursaddr);
  916.     state = normal_putch;
  917. }
  918.  
  919. /*
  920.  * putesc(v, c): handle the control sequence ESC c
  921.  */
  922.  
  923. static void
  924. putesc(v, c)
  925.     SCREEN *v;
  926.     int c;
  927. {
  928.     int i;
  929.     int cx, cy;
  930.  
  931.     cx = v->cx; cy = v->cy;
  932.  
  933.     switch (c) {
  934.     case 'A':        /* cursor up */
  935.         if (cy) {
  936. moveup:            v->cy = --cy;
  937.             v->cursaddr -= v->linelen;
  938.         }
  939.         break;
  940.     case 'B':        /* cursor down */
  941.         if (cy < v->maxy) {
  942.             v->cy = ++cy;
  943.             v->cursaddr += v->linelen;
  944.         }
  945.         break;
  946.     case 'C':        /* cursor right */
  947.         if (cx < v->maxx) {
  948.             if ((i = v->planes-1) && (cx & 1))
  949.                 v->cursaddr += i + i;
  950.             v->cx = ++cx;
  951.             v->cursaddr++;
  952.         }
  953.         break;
  954.     case 'D':        /* cursor left */
  955.         if (cx) {
  956.             v->cx = --cx;
  957.             v->cursaddr--;
  958.             if ((i = v->planes-1) && (cx & 1))
  959.                 v->cursaddr -= i + i;
  960.         }
  961.         break;
  962.     case 'E':        /* clear home */
  963.         clear(v);
  964.         /* fall through... */
  965.     case 'H':        /* cursor home */
  966.         v->cx = 0; v->cy = 0;
  967.         v->cursaddr = base;
  968.         break;
  969.     case 'I':        /* cursor up, insert line */
  970.         if (cy == 0) {
  971.             insert_line(v, 0);
  972.         }
  973.         else
  974.             goto moveup;
  975.         break;
  976.     case 'J':        /* clear below cursor */
  977.         clrfrom(v, cx, cy, v->maxx, v->maxy);
  978.         break;
  979.     case 'K':        /* clear remainder of line */
  980.         clrfrom(v, cx, cy, v->maxx, cy);
  981.         break;
  982.     case 'L':        /* insert a line */
  983.         v->cx = 0;
  984.         i = cy + cy;
  985.         i += i;
  986.         v->cursaddr = base + *(long *)(rowoff + i);
  987.         insert_line(v, cy);
  988.         break;
  989.     case 'M':        /* delete line */
  990.         v->cx = 0;
  991.         i = cy + cy;
  992.         i += i;
  993.         v->cursaddr = base + *(long *)(rowoff + i);
  994.         delete_line(v, cy);
  995.         break;
  996.     case 'Q':        /* EXTENSION: quote-next-char */
  997.         state = quote_putch;
  998.         return;
  999.     case 'Y':
  1000.         state = escy_putch;
  1001.         return;        /* YES, this should be 'return' */
  1002.  
  1003.     case 'b':
  1004.         state = setfgcol;
  1005.         return;
  1006.     case 'c':
  1007.         state = setbgcol;
  1008.         return;
  1009.     case 'd':        /* clear to cursor position */
  1010.         clrfrom(v, 0, 0, cx, cy);
  1011.         break;
  1012.     case 'e':        /* enable cursor */
  1013.         v->flags |= CURS_ON;
  1014.         v->hidecnt = 1;    /* so --v->hidecnt shows the cursor */
  1015.         break;
  1016.     case 'f':        /* cursor off */
  1017.         v->hidecnt++;
  1018.         v->flags &= ~CURS_ON;
  1019.         break;
  1020.     case 'j':        /* save cursor position */
  1021.         v->savex = v->cx;
  1022.         v->savey = v->cy;
  1023.         break;
  1024.     case 'k':        /* restore saved position */
  1025.         gotoxy(v, v->savex, v->savey);
  1026.         break;
  1027.     case 'l':        /* clear line */
  1028.         v->cx = 0;
  1029.         i = cy + cy;
  1030.         i += i;
  1031.         v->cursaddr = base + *(long *)(rowoff + i);
  1032.         clrline(v, cy);
  1033.         break;
  1034.     case 'o':        /* clear from start of line to cursor */
  1035.         clrfrom(v, 0, cy, cx, cy);
  1036.         break;
  1037.     case 'p':        /* reverse video on */
  1038.         v->flags |= FINVERSE;
  1039.         break;
  1040.     case 'q':        /* reverse video off */
  1041.         v->flags &= ~FINVERSE;
  1042.         break;
  1043.     case 't':        /* EXTENSION: set cursor flash rate */
  1044.         state = setcurs;
  1045.         return;
  1046.     case 'v':        /* wrap on */
  1047.         v->flags |= FWRAP;
  1048.         break;
  1049.     case 'w':
  1050.         v->flags &= ~FWRAP;
  1051.         break;
  1052.     }
  1053.     state = normal_putch;
  1054. }
  1055.  
  1056. /*
  1057.  * escy1_putch(v, c): for when an ESC Y + char has been seen
  1058.  */
  1059. static void
  1060. escy1_putch(v, c)
  1061.     SCREEN *v;
  1062.     int c;
  1063. {
  1064. #if 0
  1065.     gotoxy(v, c - ' ', escy1 - ' ');
  1066. #else
  1067.     /* some (un*x) termcaps seem to always set the hi bit on
  1068.        cm args (cm=\EY%+ %+ :) -> drop that unless the screen
  1069.        is bigger.    -nox
  1070.     */
  1071.     gotoxy(v, (c - ' ') & (v->maxx|0x7f), (escy1 - ' ') & (v->maxy|0x7f));
  1072. #endif
  1073.     state = normal_putch;
  1074. }
  1075.  
  1076. /*
  1077.  * escy_putch(v, c): for when an ESC Y has been seen
  1078.  */
  1079. static void
  1080. escy_putch(v, c)
  1081.     SCREEN *v;
  1082.     int c;
  1083. {
  1084.     UNUSED(v);
  1085.     escy1 = c;
  1086.     state = escy1_putch;
  1087. }
  1088.  
  1089. /*
  1090.  * normal_putch(v, c): put character 'c' on screen 'v'. This is the default
  1091.  * for when no escape, etc. is active
  1092.  */
  1093.  
  1094. static void
  1095. normal_putch(v, c)
  1096.     SCREEN *v;
  1097.     int c;
  1098. {
  1099.     register int i;
  1100.  
  1101. /* control characters */
  1102.     if (c < ' ') {
  1103.         switch (c) {
  1104.         case '\r':
  1105. col0:            v->cx = 0;
  1106.             i = v->cy + v->cy;
  1107.             i += i;
  1108.             v->cursaddr = base + *(long *)(rowoff + i);
  1109.             return;
  1110.         case '\n':
  1111.             if (v->cy == v->maxy) {
  1112.                 scroll(v);
  1113.             } else {
  1114.                 v->cy++;
  1115.                 v->cursaddr += v->linelen;
  1116.             }
  1117.             return;
  1118.         case '\b':
  1119.             if (v->cx) {
  1120.                 v->cx--;
  1121.                 v->cursaddr--;
  1122.                 if ((i = v->planes-1) && (v->cx & 1))
  1123.                     v->cursaddr -= i+i;
  1124.             }
  1125.             return;
  1126.         case '\007':        /* BELL */
  1127.             (void)bconout(CONDEV, 7);
  1128.             return;
  1129.         case '\033':        /* ESC */
  1130.             state = putesc;
  1131.             return;
  1132.         case '\t':
  1133.             if (v->cx < v->maxx) {
  1134.             /* this can't be register for an ANSI compiler */
  1135.                 union {
  1136.                     long l;
  1137.                     short i[2];
  1138.                 } j;
  1139.                 j.l = 0;
  1140.                 j.i[1] = 8 - (v->cx & 7);
  1141.                 v->cx += j.i[1];
  1142.                 if (v->cx - v->maxx > 0) {
  1143.                     j.i[1] = v->cx - v->maxx;
  1144.                     v->cx = v->maxx;
  1145.                 }
  1146.                 v->cursaddr += j.l;
  1147.                 if ((i = v->planes-1)) {
  1148.                     if (j.l & 1)
  1149.                         j.i[1]++;
  1150.                     do v->cursaddr += j.l;
  1151.                     while (--i);
  1152.                 }
  1153.             }
  1154.             return;
  1155.         default:
  1156.             return;
  1157.         }
  1158.     }
  1159.  
  1160.     (*vpaint)(v, c, v->cursaddr);
  1161.     v->cx++;
  1162.     if (v->cx > v->maxx) {
  1163.         if (v->flags & FWRAP) {
  1164.             normal_putch(v, '\n');
  1165.             goto col0;
  1166.         } else {
  1167.             v->cx = v->maxx;
  1168.         }
  1169.     } else {
  1170.         v->cursaddr++;
  1171.         if ((i = v->planes-1) && !(v->cx & 1))    /* new word */
  1172.             v->cursaddr += i + i;
  1173.     }
  1174. }
  1175.  
  1176. INLINE static void
  1177. put_ch(v, c)
  1178.     SCREEN *v;
  1179.     int c;
  1180. {
  1181.     (*state)(v, c & 0x00ff);
  1182. }
  1183.  
  1184. static long ARGS_ON_STACK screen_open    P_((FILEPTR *f));
  1185. static long ARGS_ON_STACK screen_read    P_((FILEPTR *f, char *buf, long nbytes));
  1186. static long ARGS_ON_STACK screen_write P_((FILEPTR *f, const char *buf, long nbytes));
  1187. static long ARGS_ON_STACK screen_lseek P_((FILEPTR *f, long where, int whence));
  1188. static long ARGS_ON_STACK screen_ioctl P_((FILEPTR *f, int mode, void *buf));
  1189. static long ARGS_ON_STACK screen_close P_((FILEPTR *f, int pid));
  1190. static long ARGS_ON_STACK screen_select P_((FILEPTR *f, long p, int mode));
  1191. static void ARGS_ON_STACK screen_unselect P_((FILEPTR *f, long p, int mode));
  1192.  
  1193. extern long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  1194.  
  1195. DEVDRV screen_device = {
  1196.     screen_open, screen_write, screen_read, screen_lseek, screen_ioctl,
  1197.     null_datime, screen_close, screen_select, screen_unselect
  1198. };
  1199.  
  1200. static long ARGS_ON_STACK 
  1201. screen_open(f)
  1202.     FILEPTR *f;
  1203. {
  1204.  
  1205.     if (!current) {
  1206.         init();
  1207.     }
  1208.     ++scr_usecnt;
  1209.  
  1210.     f->flags |= O_TTY;
  1211.     return 0;
  1212. }
  1213.  
  1214. static long ARGS_ON_STACK 
  1215. screen_close(f, pid)
  1216.     FILEPTR *f;
  1217.     int pid;
  1218. {
  1219.     SCREEN *v = current;
  1220.     UNUSED(pid);
  1221.  
  1222.     if (v && f->links <= 0 && !--scr_usecnt) {
  1223.         if (hardbase) {
  1224.             v->curstimer = 0x7f;
  1225.             v->cursaddr = v->cursaddr + (oldbase-base);
  1226.             quickmove(oldbase, base, scrnsize);
  1227.             base = oldbase;
  1228.             Setscreen(oldbase, oldbase, -1);
  1229.             v->curstimer = v->period;
  1230.         }
  1231.         current = 0;
  1232.     }
  1233.     return 0;
  1234. }
  1235.  
  1236. static long ARGS_ON_STACK 
  1237. screen_write(f, buf, bytes)
  1238.     FILEPTR *f; const char *buf; long bytes;
  1239. {
  1240.     SCREEN *v = current;
  1241.     struct bios_file *b = (struct bios_file *)f->fc.index;
  1242.     long *r;
  1243.     long ret = 0;
  1244.     int c;
  1245.  
  1246.     UNUSED(f);
  1247.  
  1248.     (void)checkkeys();
  1249.     v->hidecnt++;
  1250.     v->flags |= CURS_UPD;        /* for TOS 1.0 */
  1251.     curs_off(v);
  1252.     r = (long *)buf;
  1253.     while (bytes > 0) {
  1254.         c = (int) *r++;
  1255.         put_ch(v, c);
  1256.         bytes -= 4; ret+= 4;
  1257.     }
  1258.     if (v->hidecnt > 0)
  1259.         --v->hidecnt;
  1260.     else
  1261.         v->hidecnt = 0;
  1262.     curs_on(v);
  1263.     v->flags &= ~CURS_UPD;
  1264.     if (ret > 0) {
  1265.         b->xattr.atime = b->xattr.mtime = timestamp;
  1266.         b->xattr.adate = b->xattr.mdate = datestamp;
  1267.     }
  1268.     return ret;
  1269. }
  1270.  
  1271. static long ARGS_ON_STACK 
  1272. screen_read(f, buf, bytes)
  1273.     FILEPTR *f; char *buf; long bytes;
  1274. {
  1275.     struct bios_file *b = (struct bios_file *)f->fc.index;
  1276.     long *r, ret = 0;
  1277.  
  1278.     r = (long *)buf;
  1279.  
  1280.     while (bytes > 0) {
  1281.         if ( (f->flags & O_NDELAY) && !bconstat(CONDEV) )
  1282.             break;
  1283.         *r++ = bconin(CONDEV) & 0x7fffffffL;
  1284.         bytes -= 4; ret += 4;
  1285.     }
  1286.     if (ret > 0) {
  1287.         b->xattr.atime = timestamp;
  1288.         b->xattr.adate = datestamp;
  1289.     }
  1290.     return ret;
  1291. }
  1292.  
  1293. static long ARGS_ON_STACK 
  1294. screen_lseek(f, where, whence)
  1295.     FILEPTR *f;
  1296.     long where;
  1297.     int whence;
  1298. {
  1299. /* terminals always are at position 0 */
  1300.     UNUSED(f); UNUSED(where);
  1301.     UNUSED(whence);
  1302.     return 0;
  1303. }
  1304.  
  1305. static long ARGS_ON_STACK 
  1306. screen_ioctl(f, mode, buf)
  1307.     FILEPTR *f; int mode; void *buf;
  1308. {
  1309.     long *r = (long *)buf;
  1310.     struct winsize *w;
  1311.  
  1312.     UNUSED(f);
  1313.  
  1314.     if (mode == FIONREAD) {
  1315.         if (bconstat(CONDEV))
  1316.             *r = 1;
  1317.         else
  1318.             *r = 0;
  1319.     }
  1320.     else if (mode == FIONWRITE) {
  1321.             *r = 1;
  1322.     }
  1323.     else if (mode == FIOEXCEPT) {
  1324.             *r = 0;
  1325.     }
  1326.     else if (mode == TIOCFLUSH) {
  1327. /* BUG: this should flush the input/output buffers */
  1328.         return 0;
  1329.     }
  1330.     else if (mode == TIOCGWINSZ) {
  1331.         w = (struct winsize *)buf;
  1332.         w->ws_row = current->maxy+1;
  1333.         w->ws_col = current->maxx+1;
  1334.     }
  1335.     else if (mode >= TCURSOFF && mode <= TCURSGRATE) {
  1336.         SCREEN *v = current;
  1337.         switch(mode) {
  1338.         case TCURSOFF:
  1339.             curs_off(v);
  1340.             v->hidecnt++;
  1341.             v->flags &= ~CURS_ON;
  1342.             break;
  1343.         case TCURSON:
  1344.             v->flags |= CURS_ON;
  1345.             v->hidecnt = 0;
  1346.             curs_on(v);
  1347.             break;
  1348.         case TCURSBLINK:
  1349.             curs_off(v);
  1350.             v->flags |= CURS_FLASH;
  1351.             curs_on(v);
  1352.             break;
  1353.         case TCURSSTEADY:
  1354.             curs_off(v);
  1355.             v->flags &= ~CURS_FLASH;
  1356.             curs_on(v);
  1357.             break;
  1358.         case TCURSSRATE:
  1359.             v->period = *((short *)buf);
  1360.             break;
  1361.         case TCURSGRATE:
  1362.             return v->period;
  1363.         }
  1364.     } else
  1365.         return EINVFN;
  1366.  
  1367.     return 0;
  1368. }
  1369.  
  1370. static long ARGS_ON_STACK 
  1371. screen_select(f, p, mode)
  1372.     FILEPTR *f; long p; int mode;
  1373. {
  1374.     struct tty *tty = (struct tty *)f->devinfo;
  1375.     int dev = CONDEV;
  1376.  
  1377.     if (mode == O_RDONLY) {
  1378.         if (bconstat(dev)) {
  1379.             return 1;
  1380.         }
  1381.         if (tty) {
  1382.         /* avoid collisions with other processes */
  1383.             if (tty->rsel)
  1384.                 return 2;    /* collision */
  1385.             tty->rsel = p;
  1386.         }
  1387.         return 0;
  1388.     } else if (mode == O_WRONLY) {
  1389.         return 1;
  1390.     }
  1391.     /* default -- we don't know this mode, return 0 */
  1392.     return 0;
  1393. }
  1394.  
  1395. static void ARGS_ON_STACK 
  1396. screen_unselect(f, p, mode)
  1397.     FILEPTR *f;
  1398.     long p;
  1399.     int mode;
  1400. {
  1401.     struct tty *tty = (struct tty *)f->devinfo;
  1402.  
  1403.     if (tty) {
  1404.         if (mode == O_RDONLY && tty->rsel == p)
  1405.             tty->rsel = 0;
  1406.         else if (mode == O_WRONLY && tty->wsel == p)
  1407.             tty->wsel = 0;
  1408.     }
  1409. }
  1410.  
  1411. #endif /* FASTTEXT */
  1412.